#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# cron: 30 22 * * *
# new Env("新江北任务每日统计")

import os
import re
import glob
import json
import logging
import requests
from datetime import datetime, timedelta
from collections import defaultdict

# 配置日志格式
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger("XinJiangBeiStats")

# ====================== 配置区域 ======================
LOG_DIR_PATTERN = "/ql/data/log/XiaoMao_新江北_*"  # 日志目录模式（支持通配符）
TIME_RANGE_HOURS = 24  # 分析最近多少小时的日志
DEBUG_MODE = False      # 设置为True启用详细调试日志
REPORT_FILE = "/ql/data/log/Message/PUSH_xjb.log"  # 报告保存路径
# =====================================================

# 在logger定义后设置调试模式
if DEBUG_MODE:
    logger.setLevel(logging.DEBUG)
    logger.debug("调试模式已启用")

def parse_xjb_logs(log_content, account_data):
    """
    解析新江北任务日志内容并提取统计信息
    """
    # 编译正则表达式 - 使用更宽松的匹配规则
    account_section_pattern = re.compile(r'👤\s*开始处理账号:\s*(\d+)')
    account_points_pattern = re.compile(r'💰\s*当前积分:\s*(\d+)')
    lottery_result_pattern = re.compile(r'🎉\s*抽奖获得支付宝红包:\s*([\d.]+)元')
    exchange_success_pattern = re.compile(r'✅\s*兑换成功:?\s*领奖成功')
    exchange_fail_pattern = re.compile(r'❌\s*兑换失败:?\s*(.+)')
    task_progress_pattern = re.compile(r'📌\s*任务【(.+)】进度:\s*(\d+)/(\d+)')
    task_completed_pattern = re.compile(r'✅\s*任务【(.+)】已完成')
    
    current_account = None
    lines = log_content.split('\n')
    
    for line in lines:
        # 宽松处理空行
        if not line.strip():
            continue
            
        # 调试日志：打印处理的行
        logger.debug(f"处理行: {line}")
            
        # 检测账号区块开始 - 更宽松的匹配
        section_match = account_section_pattern.search(line)
        if section_match:
            current_account = section_match.group(1)
            if current_account not in account_data:
                account_data[current_account] = {
                    'points': 0,
                    'lottery_amount': 0.0,
                    'exchange_success': False,
                    'exchange_fail_reason': None,
                    'tasks': {},
                    'completed_tasks': [],
                    'warnings': []
                }
            logger.debug(f"检测到账号区块: {current_account}")
            continue
            
        if not current_account:
            continue
            
        # 提取积分信息 - 更宽松的匹配
        points_match = account_points_pattern.search(line)
        if points_match:
            points = int(points_match.group(1))
            account_data[current_account]['points'] = points
            logger.debug(f"{current_account} 积分: {points}")
            continue
            
        # 提取抽奖结果 - 更宽松的匹配
        lottery_match = lottery_result_pattern.search(line)
        if lottery_match:
            amount = float(lottery_match.group(1))
            account_data[current_account]['lottery_amount'] = amount
            logger.debug(f"{current_account} 抽奖获得红包: {amount}元")
            continue
            
        # 提取兑换成功信息 - 更宽松的匹配
        exchange_success_match = exchange_success_pattern.search(line)
        if exchange_success_match:
            account_data[current_account]['exchange_success'] = True
            logger.debug(f"{current_account} 兑换成功")
            continue
            
        # 提取兑换失败信息 - 更宽松的匹配
        exchange_fail_match = exchange_fail_pattern.search(line)
        if exchange_fail_match:
            reason = exchange_fail_match.group(1).strip()
            account_data[current_account]['exchange_fail_reason'] = reason
            account_data[current_account]['warnings'].append({
                'type': 'exchange_fail',
                'message': reason
            })
            logger.debug(f"{current_account} 兑换失败: {reason}")
            continue
            
        # 提取任务进度 - 更宽松的匹配
        task_progress_match = task_progress_pattern.search(line)
        if task_progress_match:
            task_name = task_progress_match.group(1)
            completed = int(task_progress_match.group(2))
            total = int(task_progress_match.group(3))
            
            if task_name not in account_data[current_account]['tasks']:
                account_data[current_account]['tasks'][task_name] = {
                    'completed': completed,
                    'total': total
                }
            else:
                # 更新进度
                account_data[current_account]['tasks'][task_name]['completed'] = completed
            logger.debug(f"{current_account} 任务[{task_name}]进度: {completed}/{total}")
            continue
            
        # 提取已完成任务 - 更宽松的匹配
        task_completed_match = task_completed_pattern.search(line)
        if task_completed_match:
            task_name = task_completed_match.group(1)
            if task_name not in account_data[current_account]['completed_tasks']:
                account_data[current_account]['completed_tasks'].append(task_name)
            logger.debug(f"{current_account} 任务[{task_name}]已完成")
            continue
    
    return account_data

def process_log_directories():
    """
    处理日志目录并解析所有匹配的日志文件
    返回账号统计数据
    """
    # 计算时间范围（最近N小时）
    time_threshold = datetime.now() - timedelta(hours=TIME_RANGE_HOURS)
    logger.info(f"分析时间范围: {time_threshold.strftime('%Y-%m-%d %H:%M:%S')} 至今")
    
    account_data = {}
    processed_files = 0
    skipped_files = 0
    
    # 获取所有匹配的日志文件（按时间倒序）
    all_files = []
    for log_dir in glob.glob(LOG_DIR_PATTERN):
        if not os.path.isdir(log_dir):
            continue
            
        for filename in os.listdir(log_dir):
            if filename.endswith('.log'):
                file_path = os.path.join(log_dir, filename)
                file_mtime = datetime.fromtimestamp(os.path.getmtime(file_path))
                all_files.append((file_path, file_mtime))
    
    # 按修改时间倒序排序
    all_files.sort(key=lambda x: x[1], reverse=True)
    
    # 处理日志文件
    for file_path, file_mtime in all_files:
        if file_mtime < time_threshold:
            skipped_files += 1
            logger.debug(f"跳过旧文件: {os.path.basename(file_path)} - {file_mtime}")
            continue
            
        try:
            logger.info(f"分析文件: {os.path.basename(file_path)}")
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
                account_data = parse_xjb_logs(content, account_data)
                processed_files += 1
                
                # 检查数据完整性 - 如果有账号数据，停止处理更多文件
                if account_data:
                    logger.info("找到有效账号数据，停止处理更多文件")
                    break
                    
        except Exception as e:
            logger.error(f"文件解析失败: {file_path} - {str(e)}")
    
    logger.info(f"文件处理完成: 已处理 {processed_files} 个文件, 跳过 {skipped_files} 个")
    return account_data

def generate_table_report(account_data):
    """生成表格格式的统计报告"""
    if not account_data:
        return "⚠️ 未找到有效的账号统计信息", {}
    
    # 计算总计
    totals = {
        'points': 0,
        'success_amount': 0.0,
        'fail_amount': 0.0,
        'accounts': 0,
        'exchange_fail_count': 0,
        'completed_tasks': defaultdict(int)
    }
    
    # 构建表格报告
    report_lines = [
        "📊 新江北任务每日统计报告",
        "=" * 60,
        "📈 全局汇总:"
    ]
    
    # 添加全局汇总信息
    report_lines.append(f"    👥 总账号数: {len(account_data)}个")
    
    # 计算积分总计
    total_points = sum(data['points'] for data in account_data.values())
    totals['points'] = total_points
    report_lines.append(f"    💰 总积分: {total_points}")
    
    # 计算兑换情况
    success_amount = 0.0
    fail_amount = 0.0
    fail_count = 0
    
    for data in account_data.values():
        if data['lottery_amount'] > 0:
            if data['exchange_success']:
                success_amount += data['lottery_amount']
            else:
                fail_amount += data['lottery_amount']
                fail_count += 1
    
    totals['success_amount'] = success_amount
    totals['fail_amount'] = fail_amount
    totals['exchange_fail_count'] = fail_count
    
    report_lines.append(f"    ✅ 兑换成功金额: {success_amount:.2f}元")
    report_lines.append(f"    ❌ 兑换失败金额: {fail_amount:.2f}元")
    report_lines.append(f"    ⚠️ 兑换失败账号数: {fail_count}个")
    report_lines.append("=" * 60)
    report_lines.append("\n📋 账号详情:")
    
    # 添加表格标题
    report_lines.append("\n账    号".ljust(20) + "积分".center(10) + "抽奖红包".center(15) + "兑换记录".center(10))
    report_lines.append("─" * 60)
    
    # 添加每个账号的信息
    for account, data in account_data.items():
        # 格式化账号信息
        account_display = f"🔷 {account}" if len(account) < 15 else f"🔷 ...{account[-11:]}"
        
        # 格式化积分
        points_display = f"💰 {data['points']}".center(10)
        
        # 格式化抽奖红包
        lottery_display = ""
        if data['lottery_amount'] > 0:
            lottery_display = f"🎫 {data['lottery_amount']}元".center(15)
        else:
            lottery_display = "".center(15)
        
        # 格式化兑换记录
        exchange_display = ""
        if data['lottery_amount'] > 0:
            if data['exchange_success']:
                exchange_display = "✅".center(10)
            else:
                exchange_display = "❌".center(10)
        else:
            exchange_display = "-".center(10)
        
        # 添加账号行
        report_lines.append(
            account_display.ljust(20) + 
            points_display + 
            lottery_display + 
            exchange_display
        )
        
        # 添加分隔线
        report_lines.append("─" * 60)
    
    # 添加报告时间
    report_lines.append("=" * 60)
    report_lines.append(f"📅 报告生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    
    return "\n".join(report_lines), totals

def push_plus_notify(title, content):
    """
    使用PUSH_PLUS推送通知
    """
    token = os.environ.get('PUSH_PLUS_TOKEN')
    if not token:
        logger.error("未找到PUSH_PLUS_TOKEN环境变量，无法发送通知")
        return False
    
    try:
        # PUSH_PLUS API地址
        url = "http://www.pushplus.plus/send"
        
        # 请求数据
        data = {
            "token": token,
            "title": title,
            "content": content,
            "template": "txt"
        }
        
        # 发送请求
        response = requests.post(url, json=data)
        result = response.json()
        
        if response.status_code == 200 and result.get("code") == 200:
            logger.info("PUSH_PLUS通知发送成功")
            return True
        else:
            logger.error(f"PUSH_PLUS通知发送失败: {result.get('msg', '未知错误')}")
            return False
    except Exception as e:
        logger.error(f"发送PUSH_PLUS通知时出错: {str(e)}")
        return False

def send_notification(title, content):
    """
    发送通知
    """
    # 使用PUSH_PLUS发送通知
    if push_plus_notify(title, content):
        return True
    
    logger.warning("PUSH_PLUS通知发送失败，尝试使用其他通知方式")
    # 这里可以添加其他通知方式，如sendNotify.js
    return False

def main():
    """主函数"""
    task_start = datetime.now()
    logger.info("开始新江北任务统计")
    
    try:
        # 步骤1: 处理日志目录
        account_data = process_log_directories()
        
        # 步骤2: 生成报告
        report, totals = generate_table_report(account_data)
        
        # 步骤3: 输出报告
        logger.info("\n" + report)
        
        # 步骤4: 保存报告到文件
        os.makedirs(os.path.dirname(REPORT_FILE), exist_ok=True)
        with open(REPORT_FILE, 'w', encoding='utf-8') as f:
            f.write(report)
        logger.info(f"统计报告已保存至: {REPORT_FILE}")
        
        # 步骤5: 发送通知
        if account_data:
            # 创建通知标题
            title = f"新江北任务统计 ({len(account_data)}账号)"
            
            # 创建通知内容
            notify_content = [
                "📊 新江北任务每日统计报告",
                "=" * 40,
                "📈 全局汇总:",
                f"    👥 总账号数: {len(account_data)}个",
                f"    💰 总积分: {totals['points']}",
                f"    ✅ 兑换成功金额: {totals['success_amount']:.2f}元",
                f"    ❌ 兑换失败金额: {totals['fail_amount']:.2f}元",
                f"    ⚠️ 兑换失败账号数: {totals['exchange_fail_count']}个",
                "=" * 40,
                "\n📋 账号详情:"
            ]
            
            # 添加表格标题
            notify_content.append("\n账    号".ljust(20) + "积分".center(10) + "抽奖红包".center(15) + "兑换记录".center(10))
            notify_content.append("─" * 40)
            
            # 添加每个账号的信息
            for account, data in account_data.items():
                # 格式化账号信息
                account_display = f"🔷 {account}" if len(account) < 15 else f"🔷 ...{account[-11:]}"
                
                # 格式化积分
                points_display = f"💰 {data['points']}".center(10)
                
                # 格式化抽奖红包
                lottery_display = ""
                if data['lottery_amount'] > 0:
                    lottery_display = f"🎫 {data['lottery_amount']}元".center(15)
                else:
                    lottery_display = "".center(15)
                
                # 格式化兑换记录
                exchange_display = ""
                if data['lottery_amount'] > 0:
                    if data['exchange_success']:
                        exchange_display = "✅".center(10)
                    else:
                        exchange_display = "❌".center(10)
                else:
                    exchange_display = "-".center(10)
                
                # 添加账号行
                notify_content.append(
                    account_display.ljust(20) + 
                    points_display + 
                    lottery_display + 
                    exchange_display
                )
                
                # 添加分隔线
                notify_content.append("─" * 40)
            
            # 添加报告时间
            notify_content.append("=" * 40)
            notify_content.append(f"📅 报告生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
            
            # 发送通知
            send_notification(title, "\n".join(notify_content))
        else:
            logger.warning("无有效数据，跳过通知发送")
        
        # 计算任务耗时
        task_duration = datetime.now() - task_start
        logger.info(f"任务总耗时: {task_duration.total_seconds():.2f} 秒")
        
        # 返回退出码（0表示成功）
        return 0
    except Exception as e:
        logger.exception(f"任务执行失败: {str(e)}")
        # 发送错误通知
        error_title = "新江北任务统计失败"
        error_content = f"任务执行出错: {str(e)}\n\n请查看日志获取详细信息"
        send_notification(error_title, error_content)
        return 1

if __name__ == "__main__":
    import sys
    from datetime import datetime
    
    # 设置时区为北京时间
    os.environ['TZ'] = 'Asia/Shanghai'
    
    exit_code = main()
    sys.exit(exit_code)